package com.gitee.candy.configer.interceptor;

import com.gitee.candy.configer.customInterface.HandlingTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author ：suyanlong
 * @date ：Created in 2020/11/11 16:28
 * @description：
 * @version: 1.0
 */
public class HandlingTimeInterceptor extends HandlerInterceptorAdapter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 处理器处理之前调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        HandlingTime handlingTime = findHandlingTime(handlerMethod);

        //获取注解中的值
        if (handlingTime != null) {
            request.setAttribute("startTime", System.currentTimeMillis());
        }
        return true;
    }

    /**
     * 在方法执行后调用
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //在方法执行后调用
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        HandlingTime handlingTime = findHandlingTime(handlerMethod);

        //获取注解中的值
        if (handlingTime != null) {
            logger.debug("方法执行时间{}ms", (System.currentTimeMillis() - Long.parseLong(request.getAttribute("startTime").toString())));
        }
    }

    /**
     * 在整个请求处理完毕后进行回调
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //在整个请求处理完毕后进行回调，也就是说视图渲染完毕或者调用方已经拿到响应

        //日志肯定是在afterCompletion之后记录的，否则中途失败了，也记录了，那就扯淡了。
        // 一定是程序正常跑完后，我们记录下那些对数据库做个增删改的操作日志进数据库。
        // 所以我们只需要继承HandlerInterceptorAdapter，并重写afterCompletion一个方法即可，
        // 因为preHandle默认是true。
    }

    /**
     * 处理器处理之前调用
     */
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }

    /**
     * 根据handlerMethod返回注解信息
     *
     * @param handlerMethod 方法对象
     * @return PermissionCheck注解
     */
    private HandlingTime findHandlingTime(HandlerMethod handlerMethod) {
        //在方法上寻找注解
        HandlingTime handlingTime = handlerMethod.getMethodAnnotation(HandlingTime.class);
        if (handlingTime == null) {
            //在类上寻找注解
            handlingTime = handlerMethod.getBeanType().getAnnotation(HandlingTime.class);
        }
        return handlingTime;
    }
}
